refactor(cli): extract turn run-once execution owner - #5380
Conversation
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Exact-head CI attribution for
None of the three failing owners is modified by this PR, and no failure points into the extracted |
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Exact-head update for
Fresh CI is running on this exact head. @cocolord @huangruiteng please review when available. No merge action was taken. |
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com> # Conflicts: # loopx/cli_commands/turn.py # tests/test_codex_operation_host.py
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Exact-head update for
Both merge commits carry |
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Exact-head update for
Fresh exact-head CI is running. No merge action was taken. |
|
This pull request has merge conflicts with Choose the remote for the base repository, not an out-of-date fork. git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEADFor a same-repository clone whose Keep the DCO |
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com> # Conflicts: # loopx/cli_commands/turn.py
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…ce-owner Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
huangruiteng
left a comment
There was a problem hiding this comment.
动机
未发现阻塞问题。评审 exact head:43507c2814a90ad5b039c9edf333deea9e0f9d7f,immutable base:3dbde34e15122b31d447a8a640139dd676e41d11。目标是把真正超预算的 Turn 命令 owner 分成可定位、可回滚的规划和执行 IO 边界,同时保持用户原来的命令、验证、结算和恢复行为。实测 base 的 turn.py 是 1135 行,超过冻结的 1114 行;新 head 的 command 为 311 行,完整执行 adapter 为 898 行,二者都受原有 1000 行默认上限约束,没有上调预算。
改动思路
采用现有 owner 的最小完整抽取,而不是新增 executor、Capability、状态机或第二套 TypeScript/Python 决策。命令保留参数/GoalRef/preflight、plan/inspect/capability-action 分支;只有普通 run-once 路径才 lazy import 执行 adapter。Python 保留 host 和 provider IO 适配合理,语义 owner、持久 journal、effect identity 和 typed settlement 规则继续复用既有实现。这是可独立验收的维护切片,不宣称完成 TypeScript migration 或整个 Goal authority roadmap。
正向旅程仍为命令 -> scoped plan -> host -> 独立 validator -> durable writeback/Todo continuation -> 单次 quota spend -> journal/readback -> 原 Turn 重放。用户没有新的开关、重复输入或确认步骤;不执行的计划和 capability action 不进入普通 host transaction。
具体改动
关键代码讲解
handle_turn_command(loopx/cli_commands/turn.py:52):保留 source-route 的显式 opt-in、原始 resumed Turn/Agent 身份检查,以及 planning/capability 的早返回;284–286 行 lazy 调用抽取后的 adapter,不执行的命令不加载它。execute_turn_run_once(turn_run_once.py:66):显式接收当前 prepared plan、registry/runtime、Goal admission、operator context;完整绑定原来的 generic/Codex/DSH host、独立 validation、completion/writeback/spend、scheduler 和 reflection 回调。没有增加新请求版本或永久并行入口。writeback_resolver(同文件 570 行)及相邻 spend/terminal resolver:仍读原 identity 的持久事实,区分 absent、unknown 和 committed;缺失 receipt 可修复,未知读回不能被假装成未执行。函数尾异常路径仍保留 journal_observation 和 effects 的未知值,而不是把执行后的异常渲染为全 false。
全部九个 changed paths 已读:两处生产 owner 抽取、六个测试文件更新实际 fault-injection/import target,并加强 plan、inspect-journal、calendar capability 不执行的断言;module-size smoke 删除旧 turn.py 特例,没有减少扫描范围。+978/-883 主要是移动,不是增加 898 行新决策规则。当前 main 83faf456f 相对于本 base 未修改这两个 CLI 文件;相关 #5417 另行承担 typed provider admission/recovery,不把本 PR 的 Python IO 移动误称为它的语义迁移。
独立检查旧执行块的 42 个 AST statements 和异常 handler 均等价,仅允许 strict_goal_admission 参数重命名、最终 assignment 转 return、已知 run-once 命令常量化三项归一化。相同六文件原生矩阵在 base/head 都是 212 passed、2 skipped。两项 skip 是原有显式 live-host release opt-in 下的模型参数 case;未启用、未进行付费模型调用,不能把 skipped 写成已验证。
对主干的风险
最大风险是抽取时丢掉 validator、source route、effect ref,或者错误地把 durable completion/扣费后的崩溃当成未发生。原生矩阵保留真实 File completion/spend checkpoint interruption、successor/terminal、receipt 恢复、Codex owned transport 和 CLI 冷加载负例,没有改成直接 mock 一个成功结果。
另在两个 immutable checkout 通过实际 CLI 和临时 File backend 运行 examples/loopx-turn-dsh-e2e-smoke.py:独立 marker 校验成立、持久 quota 仅一次,原 key replay 的四个 effect flags 全 false。只有 DSH harness 是合成 runner,生产 CLI/adapter/validator/writeback/journal 都实际执行;不声称验证真实模型、Windows 或 PostgreSQL。五组相同 CLI 输入分别覆盖 preview、非法 host JSON、缺失 host argv、非法 validator JSON,以及 Operation 关闭时传 source route,完整 error/schema/mode/validation/effect 输出一致,不只是两个 reason codes 相同。
参数转发的回归敏感性也实际验证:在临时运行时刻意丢掉 task_validator,真实 CLI 变成 validation_failed、writeback false、quota false、spend 0;撤销这个测试 mutation 后 exact head 正常 committed、validation passed、spend 1。没有修改 PR 源文件,也没有碰活跃 Goal。Ruff、配置中的 mypy(19 files)、diff whitespace 和 module-budget 都通过。semantic advisory 仅分析两个 changed sources、零 supported carriers;空结果不是语义证明,主要证据是 AST 和真实入口对比。
语义与 CI 对齐
复用现有 EffectiveAction/SettlementStepKind/Turn vocabulary;没有新 shared protocol、默认行为、generic 领域义务或扩大 actor 生命周期的命名。原有身份及独立 validation 是机器强制边界,不是 guidance。没有新的 default-off claim;现有 Operation off/on guards、被绕过的 planning/inspection 路径仍在实际测试中。按照当前 review 配置未读取、轮询或等待远端 CI;批准不自动解除最新 main 集成/merge-readiness 的独立约束。
我的整体评价
APPROVE。长期持续执行和用户体验判断均为 preserved:实际一次结算及零效果重放、完整输入诊断、真实持久恢复和源路由转发都有独立证据。边界更易定位,但不能以行数或测试数代替这些结果。相邻 future-facing pass 已应用为完整 IO owner 抽取,旧体已删除;继续拆更细 callbacks 或强行搭配无关 TS rewrite 会扩大当前维护目标,暂不需要。没有 frontend/Lark companion:九个路径不改变任何 UI、配置、消息或 wire consumer。未宣称全平台/live-host/whole-Goal 验收;批准后检查过期阻塞评审,保留 unresolved 讨论,不合并。
English verdict: APPROVE - 43507c2: The cohesive run-once IO extraction preserves 42 execution statements and the exception handler, five full CLI positive/negative observations, real File settlement and zero-effect replay. Base/head both pass 212 native cases with the same two optional live-host skips. A lost-validator mutation fails the independent public-entry oracle; the unchanged head commits exactly once. Module budget, Ruff and configured mypy pass; no merge or live-provider qualification is claimed.
Goal And Delivered Outcome
mainwithout changing Turn behavior.loopx/cli_commands/turn.pyhad grown to 1,128 lines and exceeded its historical 1,114-line exception.mainatf49b4a00870604d39fa4318da24d6dd35e72bb6e.Scope And Continuation
turn_run_once.py, retained lazy loading for non-executing commands, and updated test injection targets. Complete within this scope.Validation
fcea927f6c9664f79f3623b7a62e587eca4b67f2unitpassedstaticpassedreal_entrypointpassedpython examples/loopx-turn-dsh-e2e-smoke.pycompleted a committed Turn, spent one quota slot, and replayed with all effect flags false.regression_paritypassedstaticpassedmanualpassedSee validation disclosure guidance.
Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
N/A. This refactor does not claim progress against the TypeScript control-plane migration or shared Goal Authority RFC.
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).